import 'package:flutter/material.dart';
import 'package:flutter_demo/pages/animation/animated_widget_page.dart';
import 'package:flutter_demo/pages/base/layout_params/container_page.dart';
import 'package:flutter_demo/pages/base/layout_params/padding_page.dart';
import 'package:flutter_demo/pages/base/layout_params/physical_model_page.dart';
import 'package:flutter_demo/pages/page_with_title.dart';

import '../../conf/app_themes.dart';
import '../../conf/m3.dart';
import '../../widgets/app_widgets.dart';
import '../base/layout_params/align_page.dart';
import '../base/layout_params/opacity_page.dart';
import '../base/layout_params/positioned_page.dart';

class ImplicitlyAnimatedWidgetPage extends PageWithTitle {
  const ImplicitlyAnimatedWidgetPage()
      : super("隐式动画组件(ImplicitlyAnimatedWidget)");

  @override
  List<Widget> buildContentWidgets(BuildContext context) {
    return const [
      PrimaryTitle("简介"),
      BodyText("隐式动画组件，旨在为开发者提供简便的动画实现，对于开发者只是构建属性，与普通组"
          "件的使用无异，组件更新时自动以动画效果过渡。"),
      AppSpacer.large,
      UlItem("ImplicitlyAnimatedWidget"),
      BodyText("隐式动画组件，作为基类定义基础的动画配置，它只会在属性数值改变时执行一次动画，"
          "若有重复执行之类的复杂需求，建议使用："),
      PageLink(AnimatedWidgetPage()),
      LabelText("- curve 动画曲线（插值器），默认是先行动画"),
      LabelText("- duration 动画时长"),
      LabelText("- onEnd 动画结束回调"),
      LabelText("- createState 创建动画状态ImplicitlyAnimatedWidgetState"),
      LabelText("  - 封装内部动画实现的地方，基于AnimationController实现动画更新"),
      LabelText("  - AnimatedWidgetBaseState，状态的基础实现，订阅动画更新调用setState"
          "触发组件重建，除了变换相关的动画（缩放、位移、旋转、透明度）等通过Transition动画组"
          "件实现，其它都基本是依靠组件重建实现动画。"),
      AppSpacer.large,
      PrimaryTitle("常见的动画：透明度、位移、旋转、缩放"),
      _OpacityExample(),
      UlItem("AnimatedOpacity"),
      BodyText("透明度动画"),
      PageLink(OpacityPage()),
      LabelText("- opacity 透明度[0,1]"),
      AppSpacer.large,
      _SlideExample(),
      UlItem("AnimatedSlide"),
      BodyText("滑动动画"),
      LabelText("- offset 偏移量，相对于自身的宽高的倍数，比如(1,1)表示x+width y+height"),
      AppSpacer.large,
      _PositionedExample(),
      UlItem("AnimatedPositioned"),
      BodyText("定位动画，移动上下左右四条边，并以动画形式更新到新位置，他是动画版的"
          "Positioned，具有相同的特性和使用条件，参考："),
      PageLink(PositionedPage()),
      LabelText("- 同时移动左右或者上下边距，可以得到位移动画效果，当然这个组件不仅仅可以用于"
          "实现位移动画"),
      LabelText("- left 左边距"),
      LabelText("- top 上边距"),
      LabelText("- right 右边距"),
      LabelText("- bottom 下边距"),
      LabelText("- width 组件宽度"),
      LabelText("- height 组件高度"),
      UlItem("AnimatedPositionedDirectional"),
      BodyText("AnimatedPositioned支持布局方向的版本，建议优先使用这个"),
      AppSpacer.large,
      _RotationExample(),
      UlItem("AnimatedRotation"),
      BodyText("旋转动画"),
      LabelText("- turns 旋转角度，表示顺时针旋转圈数，这里每次点击顺时针旋转半圈"),
      NoticeText("注意：当前圈数从7修改为6时，他会表现为逆时针转一圈，所以这个动画效果跟之前设"
          "置的值有关，而不是在当前的基础上给你顺时针转7圈"),
      LabelText("- alignment 旋转中心"),
      AppSpacer.large,
      _ScaleExample(),
      UlItem("AnimatedScale"),
      BodyText("缩放动画"),
      LabelText("- scale 缩放倍率"),
      LabelText("- alignment 缩放中心"),
      AppSpacer.large,
      _SizeExample(),
      UlItem("AnimatedSize"),
      BodyText("尺寸动画，在child尺寸发生变化时，以动画形式过渡，可以认为我们有与child一样的"
          "尺寸，当child尺寸发生变化时，我们不会立刻修改自身尺寸，而是以动画的形式按照进度修改"),
      LabelText("- alignment child尺寸变化后，由于我们是延迟变化，双方实时尺寸在动画过程中"
          "不一样，此时child在我们中以何种方式对齐，默认居中"),
      AppSpacer.large,
      PrimaryTitle("特殊动画"),
      _AlignExample(),
      UlItem("AnimatedAlign"),
      BodyText("对齐动画，Align的动画版本，详细使用请参考"),
      PageLink(AlignPage()),
      LabelText("- alignment，对齐方式"),
      LabelText("- heightFactor，子组件有具体高度时，对齐组件以子组件高度倍数设置自身高度"),
      LabelText("- widthFactor，同样的，以子组件宽度的倍数设置自身宽度"),
      AppSpacer.large,
      _ContainerExample(),
      UlItem("AnimatedContainer"),
      BodyText("容器动画"),
      PageLink(ContainerPage()),
      AppSpacer.large,
      _TextStyleExample(),
      UlItem("AnimatedDefaultTextStyle"),
      BodyText("默认文本样式动画"),
      AppSpacer.large,
      _PaddingExample(),
      UlItem("AnimatedPadding"),
      BodyText("边距动画"),
      PageLink(PaddingPage()),
      AppSpacer.large,
      _PhysicalModelExample(),
      UlItem("AnimatedPhysicalModel"),
      BodyText("物理模型动画"),
      PageLink(PhysicalModelPage()),
      AppSpacer.large,
      _ThemeExample(),
      AppSpacer.mini,
      UlItem("AnimatedTheme"),
      BodyText("主题动画"),
    ];
  }
}

typedef _WidgetBuilder = Widget Function(
    BuildContext context, Widget clickableChild, int clickTimes);
//region 通过点击触发动画----------------------------------------------------------

class _ClickTickAnimatedWidget extends StatefulWidget {
  final _WidgetBuilder builder;

  const _ClickTickAnimatedWidget(this.builder);

  @override
  State<StatefulWidget> createState() {
    return _ClickTickAnimatedWidgetState();
  }
}

class _ClickTickAnimatedWidgetState extends State<_ClickTickAnimatedWidget> {
  var clickTimes = 0;

  @override
  Widget build(BuildContext context) {
    return widget.builder(
      context,
      InkWell(
        onTap: () {
          setState(() {
            clickTimes++;
          });
        },
        child: Container(
          width: 40,
          height: 40,
          color: Theme.of(context).colorScheme.primary,
          alignment: Alignment.center,
          child: Text(
            "click me",
            style: TextStyle(color: Theme.of(context).colorScheme.onPrimary),
          ),
        ),
      ),
      clickTimes,
    );
  }
}

//endregion

class _OpacityExample extends StatelessWidget {
  const _OpacityExample();

  @override
  Widget build(BuildContext context) {
    return _ClickTickAnimatedWidget(
      (context, child, clickTimes) {
        return AnimatedOpacity(
          opacity: clickTimes % 2 == 0 ? 1.0 : 0.5,
          duration: const Duration(milliseconds: 500),
          child: child,
        );
      },
    );
  }
}

class _SlideExample extends StatelessWidget {
  const _SlideExample();

  @override
  Widget build(BuildContext context) {
    return _ClickTickAnimatedWidget(
      (context, child, clickTimes) {
        return AnimatedSlide(
          offset: Offset(clickTimes % 2 == 0 ? 0 : 0.5, 0),
          duration: const Duration(milliseconds: 500),
          child: child,
        );
      },
    );
  }
}

class _PositionedExample extends StatelessWidget {
  const _PositionedExample();

  @override
  Widget build(BuildContext context) {
    return _ClickTickAnimatedWidget(
      (context, child, clickTimes) {
        return SizedBox(
          height: 40,
          child: Stack(
            children: [
              AnimatedPositioned(
                left: clickTimes % 2 == 0 ? 0 : 100,
                // top: clickTimes % 2 == 0 ? 0 : 10,
                right: clickTimes % 2 == 0 ? 0 : -100,
                // bottom: clickTimes % 2 == 0 ? 0 : -10,
                // width: 100,
                // height: 40,
                duration: const Duration(milliseconds: 500),
                child: child,
              )
            ],
          ),
        );
      },
    );
  }
}

class _RotationExample extends StatelessWidget {
  const _RotationExample();

  @override
  Widget build(BuildContext context) {
    return _ClickTickAnimatedWidget(
      (context, child, clickTimes) {
        return AnimatedRotation(
          turns: clickTimes / 2,
          alignment: Alignment.center,
          duration: const Duration(milliseconds: 500),
          child: child,
        );
      },
    );
  }
}

class _ScaleExample extends StatelessWidget {
  const _ScaleExample();

  @override
  Widget build(BuildContext context) {
    return _ClickTickAnimatedWidget(
      (context, child, clickTimes) {
        return AnimatedScale(
          scale: clickTimes % 2 == 0 ? 1.0 : 0.5,
          alignment: Alignment.center,
          duration: const Duration(milliseconds: 500),
          child: child,
        );
      },
    );
  }
}

class _SizeExample extends StatelessWidget {
  const _SizeExample();

  @override
  Widget build(BuildContext context) {
    return _ClickTickAnimatedWidget(
      (context, child, clickTimes) {
        return AnimatedSize(
          alignment: Alignment.center,
          duration: const Duration(milliseconds: 500),
          child: SizedBox(
            height: clickTimes % 2 == 0 ? 40 : 80,
            child: child,
          ),
        );
      },
    );
  }
}

class _AlignExample extends StatelessWidget {
  const _AlignExample();

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        _ClickTickAnimatedWidget(
          (context, child, clickTimes) {
            return AnimatedAlign(
              alignment: clickTimes % 2 == 0
                  ? AlignmentDirectional.centerStart
                  : AlignmentDirectional.centerEnd,
              duration: const Duration(milliseconds: 500),
              child: SizedBox(
                width: 160,
                child: child,
              ),
            );
          },
        ),
        AppSpacer.mini,
        _ClickTickAnimatedWidget(
          (context, child, clickTimes) {
            return AnimatedAlign(
              alignment: clickTimes % 2 == 0
                  ? AlignmentDirectional.centerStart
                  : AlignmentDirectional.centerEnd,
              widthFactor: 2,
              duration: const Duration(milliseconds: 500),
              child: SizedBox(
                width: 160,
                child: child,
              ),
            );
          },
        ),
      ],
    );
  }
}

class _ContainerExample extends StatelessWidget {
  const _ContainerExample();

  @override
  Widget build(BuildContext context) {
    return _ClickTickAnimatedWidget(
      (context, child, clickTimes) {
        return Row(
          children: [
            AnimatedContainer(
              width: clickTimes % 2 == 0 ? 40 : 80,
              height: clickTimes % 2 == 0 ? 40 : 80,
              color: clickTimes % 2 == 0 ? Colors.blue : Colors.green,
              duration: const Duration(milliseconds: 500),
              alignment: Alignment.center,
              child: child,
            )
          ],
        );
      },
    );
  }
}

class _TextStyleExample extends StatelessWidget {
  const _TextStyleExample();

  @override
  Widget build(BuildContext context) {
    return _ClickTickAnimatedWidget(
      (context, child, clickTimes) {
        return AnimatedDefaultTextStyle(
          style: clickTimes % 2 == 0
              ? Theme.of(context).textTheme.bodySmall!
              : Theme.of(context).textTheme.bodyLarge!,
          duration: const Duration(milliseconds: 500),
          child: child,
        );
      },
    );
  }
}

class _PaddingExample extends StatelessWidget {
  const _PaddingExample();

  @override
  Widget build(BuildContext context) {
    return _ClickTickAnimatedWidget(
      (context, child, clickTimes) {
        return Row(
          children: [
            AnimatedPadding(
              padding: EdgeInsetsDirectional.all(clickTimes % 2 == 0 ? 0 : 20),
              duration: const Duration(milliseconds: 500),
              child: child,
            )
          ],
        );
      },
    );
  }
}

class _PhysicalModelExample extends StatelessWidget {
  const _PhysicalModelExample();

  @override
  Widget build(BuildContext context) {
    return _ClickTickAnimatedWidget(
      (context, child, clickTimes) {
        return Column(
          children: [
            AnimatedPhysicalModel(
              shape: BoxShape.rectangle,
              borderRadius: clickTimes % 2 == 0
                  ? M3.connerRadiusExtraSmall
                  : M3.connerRadiusLarge,
              clipBehavior: Clip.antiAlias,
              color: clickTimes % 2 == 0 ? Colors.blue : Colors.green,
              shadowColor: clickTimes % 2 == 0 ? Colors.blue : Colors.green,
              elevation: clickTimes % 2 == 0 ? 10 : 20,
              duration: const Duration(milliseconds: 500),
              child: child,
            ),
            AppSpacer.large,
          ],
        );
      },
    );
  }
}

class _ThemeExample extends StatelessWidget {
  const _ThemeExample();

  @override
  Widget build(BuildContext context) {
    return _ClickTickAnimatedWidget(
      (context, child, clickTimes) {
        return AnimatedTheme(
          data: clickTimes % 2 == 0
              ? AppThemeWithCustomColor.light
              : AppThemeWithCustomColor.dark,
          duration: const Duration(milliseconds: 500),
          child: Column(
            children: [
              Card(
                child: Container(
                  height: 40,
                  alignment: Alignment.center,
                  child: const Text("test theme"),
                ),
              ),
              child,
            ],
          ),
        );
      },
    );
  }
}
